<?php
/**
 * Created by PhpStorm.
 * User: dreamy
 * Date: 2019-05-25
 * Time: 11:16
 */
namespace common\services;

use common\models\Tally;
use common\models\TallyAccount;
use common\models\TallyCategory;
use common\models\TallyRecord;
use Yii;
use yii\helpers\ArrayHelper;
use yii\helpers\Json;

/**
 * Class TallyAccountService
 * @package common\services
 * 账户管理
 */
class TallyAccountService extends BaseService
{
    /**
     * 缓存存储KEY
     */
    const CACHE_BUCKET = 'TallyAccount:';

    /**
     * 缓存有效期
     */
    const CACHE_TIMEOUT = 3600;

    /**
     * @param $id integer 账户id
     * @param $uid integer 用户id
     * @throws
     * @return string
     * 根据Id 获取账户名称
     */
    public static function getTitleFromUserScope($id,$uid)
    {
        $list = self::getListAllByUid($uid);
        $foundKey = array_search($id, array_column($list, 'id'));
        return isset($list[$foundKey]) ? ArrayHelper::getValue($list[$foundKey],'title') : null;
    }

    /**
     * @param $id integer 账户id
     * @throws
     * @return string
     * 根据Id 获取账户名称
     */
    public static function getTitleGlobal($id)
    {
        $row = TallyAccount::find()->where(['id'=>$id])->asArray()->one();
        return ArrayHelper::getValue($row,'title',null) ;
    }

    /**
     * @param $uid
     * @return array|mixed|\yii\db\ActiveRecord[]
     * @throws \yii\base\InvalidConfigException
     * 根据用户uid获取所有数据并缓存
     */
    public static function getListAllByUid($uid)
    {
        // 先从缓存里尝试命中
        $redis = Yii::$app->get('redis');
        $cacheList = $redis->get(self::CACHE_BUCKET.$uid);
        if(!empty($cacheList)) {
            $cacheList = json_decode($cacheList,true);
            return $cacheList ;
        }
        // 从DB获取
        $accountList = TallyAccount::find()
            ->select('*')
            ->where([
                'uid'   => $uid,
            ])
            ->limit(100)
            ->asArray()
            ->all();
        if(!empty($accountList)) {
            // 写入缓存
            $redis->setex(self::CACHE_BUCKET.$uid,self::CACHE_TIMEOUT,json_encode($accountList,JSON_UNESCAPED_UNICODE));
        }
        return $accountList ;
    }

    /**
     * @param $uid
     * @param array $condition
     * @throws
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function getListByUid($uid,$condition=[])
    {
        // 查表获取
        $where = [
            'uid'   => $uid,
        ];
        // 上级分类 默认主分类
        if(ArrayHelper::getValue($condition,'type')){
            $where['type'] = $condition['type'] ; // 收入or支出
        }
        // 账本ID
        if(ArrayHelper::getValue($condition,'tally_id')){
            $where['tally_id'] = $condition['tally_id'] ; // 账本ID
        }
        // 从DB获取
        $accountList = TallyAccount::find()
            ->select('*')
            ->where($where)
            ->limit(100)
            ->asArray()
            ->all();
        return $accountList ;
    }

    /**
     * @param array $condition
     * @throws
     * @return array|\yii\db\ActiveRecord[]
     */
    public static function getList($condition=[])
    {
        // 查表获取
        $where = [];
        // 上级分类 默认主分类
        if(ArrayHelper::getValue($condition,'type')){
            $where['type'] = $condition['type'] ; // 收入or支出
        }
        // 账本ID
        if(ArrayHelper::getValue($condition,'tally_id')){
            $where['tally_id'] = $condition['tally_id'] ; // 账本ID
        }









        // 从DB获取
        $accountList = TallyAccount::find()
            ->select('*')
            ->where($where);
        if(ArrayHelper::getValue($condition,'accounts')){
            $accountList = $accountList->andFilterWhere(['in','id',ArrayHelper::getValue($condition,'accounts')]);
        }
        $accountList = $accountList->limit(100)->orderBy('sorting ASC')
            ->asArray()
            ->all();

        $arr_tip_str = [
            '现金账户'=>0,
            '金融账户'=>1,
            '虚拟账户'=>2,
            '信用账户'=>3,
            '负债账户'=>4,
            '债权账户'=>5,
            '投资账户'=>6,
            '其他账户'=>7,
            '未知账户'=>8,
        ];
        $all_group = json_decode(ToolService::getConfig('DEFAULT_ACCOUNT_TAG'),true);
        $all_group[] = [
            'id'=>9,
            'title'=>'未知账户',
            'img_url'=>'https://static.gongsizhang.com/2023-09-22-650d781fbd5c7.png'
        ];

        foreach ($accountList as &$value){
            $value['img_url'] = $all_group[$arr_tip_str[$value['tag']]]['img_url'];
        }
        return $accountList ;
    }

    /**
     * @param $formData
     * @return bool
     */
    public static function create($formData): bool
    {
        $model = new TallyAccount();
        $model->load($formData,'');
        if ($model->validate() && $model->save()) {
            return $model->id ;
        }else{
            Yii::error('TallyAccount insert error:'.current($model->getFirstErrors()).';post:'.Json::encode($formData,JSON_UNESCAPED_UNICODE));
            self::setError(current($model->getFirstErrors()));
            return false;
        }
    }

    /**
     * @param $condition
     * @param $formData
     * @return bool
     */
    public static function update($condition,$formData)
    {
        $model = TallyAccount::find()->where($condition)->one();
        if(!$model){
            self::setError('账户不存在');
            return false ;
        }
        // 这里增加账户初始金额变动后 对当前余额造成的影响
        $oldInitMoney = ToolService::moneyFormat($model->initial_money);
        if(isset($formData['initial_money'])){
            $newInitMoney = ToolService::moneyFormat($formData['initial_money']);
            $model->money = ToolService::moneyFormat(
                ToolService::moneyFormat($model->money) + $newInitMoney - $oldInitMoney);
        }
        $model->load($formData,'');
        if ($model->validate() && $model->save()) {
            return true ;
        }else{
            Yii::error('TallyAccount save error:'.current($model->getFirstErrors()).';post:'.Json::encode($formData,JSON_UNESCAPED_UNICODE));
            self::setError(current($model->getFirstErrors()));
            return false;
        }
    }

    /**
     * @param $condition
     * @return bool
     * @throws
     */
    public static function delete($condition)
    {
        $model = TallyAccount::find()->where($condition)->one();
        if(!$model){
            self::setError('账户不存在');
            return false ;
        }
        if ($model->delete()) {
            return true ;
        }else{
            self::setError(current($model->getFirstErrors()));
            return false;
        }
    }

    /**
     * @param $condition
     * @param $updateAmount
     *
     * @return int
     * @desc 更新账户金额
     */
    public static function updateMoney($condition,$updateAmount)
    {
        return TallyAccount::updateAllCounters([
            'money' => $updateAmount
        ], $condition);
    }

    /**
     * @param array $condition 查询条件
     * @param string $field
     * @return mixed
     * @notes 账户统计
     */
    public static function sumAll($condition,$field='money')
    {
        $accountList = TallyAccount::find()
            ->select('*');
        foreach ($condition as $cond) {
            $accountList->andWhere($cond);
        }
        return $accountList ->sum($field);
    }

    /**
     * 用于账套各账户的重新核算 根据真实账单情况
     */
    public static function reCheckMoney($tallyId)
    {
        $accountList = TallyAccount::find()->select('id,title,initial_money')->where([
            'tally_id' => $tallyId
        ])->asArray()->all();
        $recordWhere = [
            'tally_id' => $tallyId,
            'state' => TallyRecord::STATE_VALID, //必须为已入账状态
        ];
        // 遍历账户计算进出项
        foreach ($accountList as &$act) {
            // 统计该账户的所有 收入 | 转账转入
            $inMoney_1 = TallyRecord::find()->where($recordWhere)
                ->andFilterWhere(['=','account_id',$act['id']])
                ->andFilterWhere(['=','type',TallyRecord::TYPE_IN])
                ->sum('amount');
            $inMoney_1 = $inMoney_1 ?: 0;
            $inMoney_2 = TallyRecord::find()->where($recordWhere)
                ->andFilterWhere(['=','account_dst_id',$act['id']])
                ->andFilterWhere(['=','type',TallyRecord::TYPE_TRANS])
                ->sum('amount');
            $inMoney_2 = $inMoney_2 ?: 0;
            // 统计账户所有 支出 | 转账转出
            $outMoney_1 = TallyRecord::find()->where($recordWhere)
                ->andFilterWhere(['=','account_id',$act['id']])
                ->andFilterWhere(['=','type',TallyRecord::TYPE_OUT])
                ->sum('amount');
            $outMoney_1 = $outMoney_1 ?: 0;
            $outMoney_2 = TallyRecord::find()->where($recordWhere)
                ->andFilterWhere(['=','account_id',$act['id']])
                ->andFilterWhere(['=','type',TallyRecord::TYPE_TRANS])
                ->sum('amount');
            $outMoney_2 = $outMoney_2 ?: 0;
            // 计算结余
            $debt = $inMoney_1 + $inMoney_2 - $outMoney_1 - $outMoney_2 ;
            $debt = ToolService::moneyFormat($debt);
            // 结余要加上之前的初始金额
            $initMoney = ToolService::moneyFormat($act['initial_money']);
            $act['debt'] = ToolService::moneyFormat($debt + $initMoney);
        }
        // 返回重新计算的账户金额数据
        return $accountList;
    }
}
